<?php
namespace Helper;

/**
 * 从es中获取数据 api
 * Class AnalysisApi
 * @package Helper
 */
class AnalysisApi
{
    /**
     * @var null
     */
    static $config = null;

    /**
     * @var null
     */
    static $logger = null;

    /**
     * @var null
     */
    static $cache  = null;

    /**
     * 参数必选项
     * @var array
     */
    static $parameters = [
        //查询所属类型，其中event代表日活，eventlogs代表事件，postback代表收益。多个逗号分隔
        'index' => null,
        //产品名，严格区分大小写。默认DollarGetter_lg2
        'app' => "DollarGetter_lg2",
        //默认为 +0800，GMT东八区
        'timezone' => "+0800",
        //查询起始时间，只要是可阅读的时间即可。如2017-01-01、-10 day、last week、2017-01-01T00:00:00
        'dateStart' => "",
        //查询结束时间，格式同上，注意查询区间是大于等于dateStart，小于dateEnd
        'dateEnd' => "",
        //除重字段，默认uudi，另外imei，device_md5
        'uniq' => "uuid",
        //聚合分组，默认date，层级逗号隔开
        'aggs' => 'date',
        //定义响应字段。详情查看文档列表。
        'source' => "",
        //以下为可选项
        'group' => '',
        'channel' => '',
        'vcode' => '',
        'offer_id' => '',
        'from' => '',
        'sdk' => '',
        'geo' => '',
        'plugin' => '',
        'mark' => '{project}-{developer}',
    ];

    /**
     * @param $params
     * @return mixed
     * @throws \Exception
     */
    static function getResponse($params)
    {
        self::config();
        $params = self::checkParams($params);
        $json = self::curl(self::$config['server']['api'], $params);
        $result = json_decode($json, true);
        if (empty($json) || $result['code'] != 0)
        {
            throw new \Exception("返回结果为空 error:{$result['error']}");
        }

        return $result['response'];
    }

    static function checkParams($params)
    {
        //index
        $index = array_filter(explode(',', trim($params['index'])));
        if (!isset($params['index']) || empty(array_intersect($index, self::$config['index'])))
        {
            throw new \Exception("index 参数无效！");
        }

        //source
        if (empty($params['source']))
        {
            throw new \Exception("source 参数无效");
        }
        $sources = [];
        foreach($index as $i)
        {
            if (empty(self::$config['source'][$i]))
            {
                throw new \Exception("source[{$i}] 未配置");
            }
            $sources = array_merge($sources, self::$config['source'][$i]);
        }
        $params['source'] = implode(',', array_intersect(explode(',', $params['source']),$sources));

        //timezone
        if (isset($params['timezone']) && !in_array($params['timezone'], self::timezone(true)))
        {
            throw new \Exception("timezone 参数无效！");
        }
        $params['timezone'] = str_replace(":", "", $params['timezone']);

        //日期起止检查
        if (!isset($params['dateStart']) || (strtotime($params['dateEnd']) < strtotime($params['dateStart'])))
        {
            throw new \Exception("dateStart or dateEnd 参数不能缺失，同时dateEnd >= dateStart");
        }

        $params['dateStart'] = date("Y-m-d", strtotime($params['dateStart'])) . "T00:00:00";
        $params['dateEnd'] = date("Y-m-d", strtotime($params['dateEnd']) + 86400) . "T00:00:00";

        $final = [];
        //获取合并参数
        foreach (self::$parameters as $key => $val)
        {
            if (!empty($val))
            {
                $final[$key] = $val;
            }
            if (!empty($params[$key]))
            {
                $final[$key] = $params[$key];
            }
        }

        return $final;
    }

    /**
     * @param $url
     * @param $params
     * @return mixed
     */
    static function curl($url, $params)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_ENCODING, 'gzip');
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);//支持链接里的301重定向
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
        $json = curl_exec($curl);
        $curlCmd = sprintf("curl -s '%s' -X POST -d '%s'", $url, urldecode(http_build_query($params)));
        self::logger()->warn($curlCmd);
        self::logger()->warn($json);
        curl_close($curl);

        return $json;
    }

    static function config()
    {
        if(null != self::$config)
            return self::$config;

        $config = require CONF_PATH.'/es.php';
        if(!isset($config["server"]) || !isset($config["index"]))
        {
            throw new \Exception("NoConfigFile");
        }

        return self::$config = $config;
    }

    static function logger()
    {
        if(null != self::$logger)
            return self::$logger;

        $Logdir = LOG_PATH;
        if(!dir($Logdir))
            mkdir($Logdir, true, 0777);

        $log = new \Monolog\Logger('ES');
        $log->pushHandler(new \Monolog\Handler\StreamHandler($Logdir."elasticsearch.log", \Monolog\Logger::WARNING));

        return self::$logger = $log;
    }

    static function cache()
    {
        if(null != self::$cache)
            return self::$cache;

        try {
            self::$cache = new \redis();
            self::$cache->connect(self::$config["redis"]["host"], self::$config["redis"]["port"]);
            self::$cache->auth(self::$config["redis"]["password"]);
        } catch (\Exception $e) {

        }
        return self::$cache;
    }

    static function timezone($keys = false)
    {
        $timezone = array (
            '-12:00' => 'UTC-12 (IDL-国际换日线)',
            '-11:00' => 'UTC-11 (MIT - 中途岛标准时间)',
            '-10:00' => 'UTC-10 (HST - 夏威夷－阿留申标准时间)',
            '-09:30' => 'UTC-9:30 (MSIT - 马克萨斯群岛标准时间)',
            '-09:00' => 'UTC-9 (AKST - 阿拉斯加标准时间)',
            '-08:00' => 'UTC-8 (PSTA - 太平洋标准时间A)',
            '-07:00' => 'UTC-7 (MST - 北美山区标准时间)',
            '-06:00' => 'UTC-6 (CST - 北美中部标准时间)',
            '-05:00' => 'UTC-5 (EST - 北美东部标准时间)',
            '-04:30' => 'UTC-4:30 (RVT - 委内瑞拉标准时间)',
            '-04:00' => 'UTC-4 (AST - 大西洋标准时间)',
            '-03:30' => 'UTC-3:30 (NST - 纽芬兰岛标准时间)',
            '-03:00' => 'UTC-3 (SAT - 南美标准时间)',
            '-02:00' => 'UTC-2 (BRT - 巴西时间)',
            '-01:00' => 'UTC-1 (CVT - 佛得角标准时间)',
            '+00:00' => 'UTC+0 (GMT - 格林威治标准时间)',
            '+01:00' => 'UTC+1 (CET - 欧洲中部时区)',
            '+02:00' => 'UTC+2 (EET - 欧洲东部时区)',
            '+03:00' => 'UTC+3 (MSK - 莫斯科时区)',
            '+03:30' => 'UTC+3:30 (IRT - 伊朗标准时间)',
            '+04:00' => 'UTC+4 (META - 中东时区A)',
            '+04:30' => 'UTC+4:30 (AFT- 阿富汗标准时间)',
            '+05:00' => 'UTC+5 (METB - 中东时区B)',
            '+05:30' => 'UTC+5:30 (IDT - 印度标准时间)',
            '+05:45' => 'UTC+5:45 (NPT - 尼泊尔标准时间)',
            '+06:00' => 'UTC+6 (BHT - 孟加拉标准时间)',
            '+06:30' => 'UTC+6:30 (MRT - 缅甸标准时间)',
            '+07:00' => 'UTC+7 (MST - 中南半岛标准时间)',
            '+08:00' => 'UTC+8 (EAT - 东亚标准时间/北京时间)',
            '+08:30' => 'UTC+8:30 (KRT- 朝鲜标准时间)',
            '+09:00' => 'UTC+9 (FET- 远东标准时间)',
            '+09:30' => 'UTC+9:30 (ACST - 澳大利亚中部标准时间)',
            '+10:00' => 'UTC+10 (AEST - 澳大利亚东部标准时间)',
            '+10:30' => 'UTC+10:30 (FAST - 澳大利亚远东标准时间)',
            '+11:00' => 'UTC+11 (VTT - 瓦努阿图标准时间)',
            '+11:30' => 'UTC+11:30 (NFT - 诺福克岛标准时间)',
            '+12:00' => 'UTC+12 (PSTB - 太平洋标准时间B)',
            '+12:45' => 'UTC+12:45 (CIT - 查塔姆群岛标准时间)',
            //'+13:00' => 'UTC+13 (PSTC - 太平洋标准时间C)',
            //'+14:00' => 'UTC+14 (PSTD - 太平洋标准时间D)',
        );
        if ($keys)
        {
            return array_keys($timezone);
        }
        return $timezone;
    }
}